﻿// Inner Fire 游戏引擎库
// DirectX图型主类
//
// Copyright (c) 2023 by 尔西大帝. All rights reserved.
//
// 这个类用于读取XML，并将其转化为交互者友好的类。
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2024-11-15

#pragma once

#include "dx_utils.h"
#include <dx_core/camera.h>
#include <dx_core/frame_resource.h>
#include <dx_core/render_item.h>
#include <dx_core/simple_mesh.h>
#include <dx_core/uploader_buffer.h>
#include <dx_effects/blur_filter.h>
#include <dx_effects/gpu_waves.h>
#include <dx_effects/render_target.h>
#include <dx_effects/sobel_filter.h>
#include <dx_lib/CubeRenderTarget.h>
#include <dx_lib/LoadM3d.h>
#include <dx_lib/ShadowMap.h>
#include <dx_lib/SkinnedData.h>
#include <dx_lib/Ssao.h>
#include <dx_lib/Waves.h>
#include <dx_model/geometry_generator.h>
#include <dx_model/material.h>
#include <dx_model/texture.h>
#include <timer.h>

using Microsoft::WRL::ComPtr;
using namespace DirectX;

namespace ifire {

class DxScene;

const UINT CubeMapSize = 512;

class DxGraphics {
public:
  DxGraphics();
  ~DxGraphics();

  friend class DxScene;

  DxGraphics(const DxGraphics& other) = delete;            // 不可复制
  DxGraphics& operator=(const DxGraphics& other) = delete; // 不可移动

  // 初始化Direct3D的基础内容
  void InitDirect3D(HWND hwnd, int width, int height);

  // 设置Direct3D的渲染管线
  void InitPipeline();

  // 更新世界矩阵
  void UpdateObjectConstants(XMMATRIX mvp);
  // 更新太阳光
  void UpdateSun(float theta, float phi);

  // 清空命令队列
  void FlushCommandQueue();

  // 当窗口大小发生改变时，执行项目
  void OnResize();

  // 更新对象缓冲区
  void UpdateObjectCBs();
  // 更新材质缓冲区
  void UpdateMaterialCBs();
  // 更新PASS缓冲区
  void UpdateMainPassCB();
  // 更新用于反射的缓冲区
  void UpdateReflectedPassCB();

  // 绘制
  void Draw();
  void Draw_Reset();
  void Draw_SetViewport();
  void Draw_SwitchToRender();
  void Draw_ClearScreen();
  void Draw_SetHeaps();
  void Draw_SetRootSignature();
  void Draw_Commit();
  void Draw_Room();
  // 对帧资源进行更迭（每帧调用一次）
  void Update();
  // 更新相机
  void UpdateCamera_OnKeyboardInput();
  void UpdateCamera_OnMouseMove(WPARAM state, int x, int y);
  void UpdateCamera_OnMouseDown(WPARAM state, int x, int y);
  void UpdateCamera_ReleaseCapture();

  // 切换帧资源
  void SwitchFrameResource();
  // 更新波浪的顶点
  void UpdateWaves();
  void AnimateMaterials();
  // 更新投影矩阵
  void UpdateProjection();

  // 控制项目
  void OnKeyboardInput_Room();     // 控制ROOM
  void OnKeyboardInput_SumLight(); // 控制阳光

  // 绘制对象
  void DrawRenderItems(
      ID3D12GraphicsCommandList* cmd, const std::vector<RenderItem*>& items);

  // 得到当前后台缓冲区的RTV
  D3D12_CPU_DESCRIPTOR_HANDLE GetBackBufferView() const;
  // 得到当前后台缓冲区
  ID3D12Resource* GetBackBuffer() const;
  // 得到当前后台缓冲区的DSV
  D3D12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const;
  // 得到当前后台缓冲区的RTV
  D3D12_CPU_DESCRIPTOR_HANDLE CurrentBackBufferView() const;
  // 得到当前后台缓冲区
  ID3D12Resource* CurrentBackBuffer() const;
  // 得到当前后台缓冲区的DSV
  D3D12_CPU_DESCRIPTOR_HANDLE DepthStencilView() const;

  // 参数获得
  float GetAspectRatio() const;
  bool Get4xMsaaState() const;
  void Set4xMsaaState(bool enable);
  // 设置窗口大小
  void SetClientSize(int width, int height);
  void SetScene(DxScene* scene);
  bool IsReady() { return device_.Get() != nullptr; }
  // 设置是否模糊
  void SetBlurEnable(bool enable) { is_blur_enable_ = enable; }
  const char* GetTitle() { return mMainWndCaption.c_str(); }

  // 创建默认缓冲区
  ComPtr<ID3D12Resource> CreateDefaultBuffer(const void* data, UINT64 data_size,
      ComPtr<ID3D12Resource>& upload_buffer);
  HRESULT LoadDDS(_In_z_ const char* szFileName,
      _Out_ ComPtr<ID3D12Resource>& texture,
      _Out_ ComPtr<ID3D12Resource>& textureUploadHeap);

  void Scene_OnKeyboardInput();
  void Scene_OnMouseMove(WPARAM state, int x, int y);
  void Scene_OnMouseDown(WPARAM state, int x, int y);
  void Scene_OnMouseUp(WPARAM state, int x, int y);

public:
  //
  // 用于累加
  //
  void VecAdd_InitPipeline();
  void VecAdd_Draw();
  void VecAdd_BuildBuffers();
  void VecAdd_BuildRootSignature();
  void VecAdd_BuildDescriptorHeaps();
  void VecAdd_BuildShadersAndInputLayout();
  void VecAdd_BuildFrameResources();
  void VecAdd_BuildPSOs();
  void VecAdd_DoComputeWork();

  //
  // 用于山水
  //
  void MountainWater_Update();
  void MountainWater_InitPipeline();
  void MountainWater_InitObjects();
  void MountainWater_BuildRootSignature();
  void MountainWater_BuildWavesRootSignature();
  void MountainWater_LoadTextures();
  void MountainWater_BuildRenderItems();
  void MountainWater_BuildMaterials();
  void MountainWater_BuildDescriptorHeaps();
  void MountainWater_BuildFrameResources();
  void MountainWater_BuildPostProcessRootSignature();
  void MountainWater_BuildSobelPostProcessRootSignature();
  void MountainWater_BuildPSOs();
  void MountainWater_Draw();
  void MountainWater_OnInput();
  void MountainWater_UpdateWavesGPU();
  void MountainWater_BuildGpuWaves();
  void CreateMeshQuad();
  void DrawFullscreenQuad(ID3D12GraphicsCommandList* cmdList);

  //
  // 房间
  //
  void Room_Update();
  void Room_InitPipeline();
  void LoadTextures_Room();
  void BuildMaterials_Room();
  void BuildRenderItems_Room();
  void BuildFrameResources_Room();
  void BuildPSOs_Room();

  //
  // 曲面细分
  //
  void Tess_Update();
  void Tess_InitPipeline();
  void Tess_Draw();
  void Tess_BuildQuadPatchGeometry();
  void Tess_BuildMaterials();
  void Tess_BuildRenderItems();
  void Tess_BuildFrameResources();
  void Tess_BuildPSOs();
  void Tess_BuildShaderAndInputLayout();
  // 贝赛尔平面
  void Tess_Patch_BuildShaderAndInputLayout();
  void Tess_Patch_BuildQuadPatchGeometry();
  void Tess_Patch_BuildRenderItems();

  //
  // 祭坛
  //
  void Altar_Update();
  void Altar_InitPipeline();
  void Altar_Draw();
  void Altar_LoadTextures();
  void Altar_BuildRootSignature();
  void Altar_BuildDescriptorHeaps();
  void Altar_BuildShadersAndInputLayout();
  void Altar_BuildMaterials();
  void Altar_BuildRenderItems();
  void Altar_BuildSkullGeometry();
  void BuildFrameResources_V2();
  void Altar_BuildPSOs();
  void Altar_UpdateObjectCBs();
  void Altar_UpdateMaterialBuffer();
  void DrawRenderItems_V2(ID3D12GraphicsCommandList* cmdList,
      const std::vector<RenderItem*>& ritems);
  void Altar_BuildShapeGeometry();

  //
  // 实例化与剔除
  //
  void Instanced_Update();
  void Instanced_InitPipeline();
  void Instanced_Draw();

  void Instanced_DrawRenderItems(ID3D12GraphicsCommandList* cmdList,
      const std::vector<RenderItem*>& ritems);
  void Instanced_LoadTextures();
  void Instanced_BuildRootSignature();
  void Instanced_BuildDescriptorHeaps();
  void Instanced_BuildShadersAndInputLayout();
  void Instanced_BuildMaterials();
  void Instanced_BuildRenderItems();
  void Instanced_BuildFrameResources();
  void Instanced_BuildPSOs();
  void Instanced_UpdateObjectCBs();
  void Instanced_UpdateMaterialBuffer();
  void Instanced_BuildShapeGeometry();
  void
  Instanced_BuildSkullGeometry(); // 独属的创建骷髅头。和之前的骷髅头是不一样的。
  void Instanced_UpdateInstanceData();

  // 射线拾取
  void Pick_Update();
  void Pick_InitPipeline();
  void Pick_Draw();
  void Pick_DrawRenderItems(ID3D12GraphicsCommandList* cmdList,
      const std::vector<RenderItem*>& ritems);
  void Pick_LoadTextures();
  void Pick_BuildRootSignature();
  void Pick_BuildDescriptorHeaps();
  void Pick_BuildShadersAndInputLayout();
  void Pick_BuildCarGeometry();
  void Pick_BuildMaterials();
  void Pick_BuildRenderItems();
  void Pick_BuildFrameResources();
  void Pick_BuildPSOs();
  void UpdateObjectCBs_V2();
  void UpdateMaterialBuffer_V2();
  void UpdateMainPassCB_V2();
  void Pick(int sx, int sy);
  void Pick_OnMouseDown(WPARAM state, int x, int y);

  // 天空盒
  void Cube_Update();
  void Cube_InitPipeline();
  void Cube_Draw();

  void Cube_LoadTextures();
  void Cube_BuildRootSignature();
  void Cube_BuildDescriptorHeaps();
  void Cube_BuildShadersAndInputLayout();
  void Cube_BuildMaterials();
  void Cube_BuildRenderItems();
  void Cube_BuildPSOs();
  // 动态立方体图
  void DynamicCube_Update();
  void DynamicCube_InitPipeline();
  void DynamicCube_Draw();
  void DynamicCube_DrawRenderItems(ID3D12GraphicsCommandList* cmdList,
      const std::vector<RenderItem*>& ritems);
  void UpdateCubeMapFacePassCBs();
  void BuildCubeFaceCamera(float x, float y, float z);
  void DynamicCube_BuildDescriptorHeaps();
  void DynamicCube_BuildCubeDepthStencil();
  void DynamicCube_BuildShadersAndInputLayout();
  void DynamicCube_BuildSkullGeometry();
  void DynamicCube_BuildShapeGeometry();
  void DynamicCube_BuildMaterials();
  void DynamicCube_BuildRenderItems();
  void DynamicCube_BuildFrameResources();
  void DynamicCube_BuildPSOs();
  void DrawSceneToCubeMap();

  //
  // 法线贴图
  //
  void Normal_Update();
  void Normal_InitPipeline();
  void Normal_Draw();
  void Normal_DrawRenderItems(ID3D12GraphicsCommandList* cmdList,
      const std::vector<RenderItem*>& ritems);
  void Normal_LoadTextures();
  void Normal_BuildRootSignature();
  void Normal_BuildDescriptorHeaps();
  void Normal_BuildShadersAndInputLayout();
  void Normal_BuildShapeGeometry();
  void Normal_BuildMaterials();
  void Normal_BuildRenderItems();
  void Normal_BuildFrameResources();
  void Normal_BuildPSOs();
  void Normal_UpdateObjectCBs();
  void Normal_UpdateMaterialBuffer();
  void Normal_UpdateMainPassCB();

  //
  // 阴影
  //

  void Shadows_Update();
  void Shadows_InitPipeline();
  void Shadows_Draw();
  void Shadows_DrawRenderItems(ID3D12GraphicsCommandList* cmdList,
      const std::vector<RenderItem*>& ritems);
  void DrawSceneToShadowMap();
  void Shadows_LoadTextures();
  void Shadows_BuildRootSignature();
  void Shadows_BuildDescriptorHeaps();
  void Shadows_BuildShadersAndInputLayout();
  void Shadows_BuildShapeGeometry();
  void Shadows_BuildSkullGeometry();
  void Shadows_BuildMaterials();
  void Shadows_BuildRenderItems();
  void Shadows_BuildFrameResources();
  void Shadows_BuildPSOs();
  void Shadows_UpdateObjectCBs();
  void Shadows_UpdateMaterialBuffer();
  void Shadows_UpdateShadowTransform();
  void Shadows_UpdateMainPassCB();
  void Shadows_UpdateShadowPassCB();
  std::array<const CD3DX12_STATIC_SAMPLER_DESC, 7> Shadows_GetStaticSamplers();

  //
  // 屏幕环境光遮蔽
  //
  void Ssao_Update();
  void Ssao_InitPipeline();
  void Ssao_Draw();
  void Ssao_DrawRenderItems(ID3D12GraphicsCommandList* cmdList,
      const std::vector<RenderItem*>& ritems);
  void Ssao_LoadTextures();
  void Ssao_BuildRootSignature();
  void Ssao_BuildSsaoRootSignature();
  void Ssao_BuildDescriptorHeaps();
  void Ssao_BuildShadersAndInputLayout();
  void Ssao_BuildShapeGeometry();
  void Ssao_BuildSkullGeometry();
  void Ssao_BuildMaterials();
  void Ssao_BuildRenderItems();
  void Ssao_BuildFrameResources();
  void Ssao_BuildPSOs();
  void Ssao_UpdateObjectCBs();
  void Ssao_UpdateMaterialBuffer();
  void Ssao_UpdateShadowTransform();
  void Ssao_UpdateMainPassCB();
  void Ssao_UpdateShadowPassCB();
  void Ssao_UpdateSsaoCB();
  void DrawNormalsAndDepth();
  void Ssao_DrawSceneToShadowMap();
  CD3DX12_CPU_DESCRIPTOR_HANDLE GetCpuSrv(int index) const;
  CD3DX12_GPU_DESCRIPTOR_HANDLE GetGpuSrv(int index) const;
  CD3DX12_CPU_DESCRIPTOR_HANDLE GetDsv(int index) const;
  CD3DX12_CPU_DESCRIPTOR_HANDLE GetRtv(int index) const;

  //
  // 骨骼动画
  //
  void Skin_Update();
  void Skin_InitPipeline();
  void Skin_Draw();
  void Skin_DrawRenderItems(ID3D12GraphicsCommandList* cmdList,
      const std::vector<RenderItem*>& ritems);
  void Skin_LoadSkinnedModel();
  void Skin_LoadTextures();
  void Skin_BuildRootSignature();
  void Skin_BuildSsaoRootSignature();
  void Skin_BuildDescriptorHeaps();
  void Skin_BuildShadersAndInputLayout();
  void Skin_BuildShapeGeometry();
  void Skin_BuildMaterials();
  void Skin_BuildRenderItems();
  void Skin_BuildFrameResources();
  void Skin_BuildPSOs();
  void Skin_UpdateObjectCBs();
  void Skin_UpdateSkinnedCBs();
  void Skin_UpdateMaterialBuffer();
  void Skin_UpdateShadowTransform();
  void Skin_UpdateMainPassCB();
  void Skin_UpdateShadowPassCB();
  void Skin_UpdateSsaoCB();
  void Skin_DrawSceneToShadowMap();
  void Skin_DrawNormalsAndDepth();

private:
  // 获得MSAA配置
  inline UINT GetMsaaSampleCount() const { return msaa_enable_ ? 4 : 1; }
  inline UINT GetMsaaSampleQuality() const {
    return msaa_enable_ ? (msaa_quality_ - 1) : 0;
  }

  // 创建Dx设备
  void CreateDevice();
  // 创建Fence
  void CreateFence();
  // 检查4xMSAA的支持
  void CheckMsaa();
  // 创建命令列表
  void CreateCommandObjects();
  // 创建交换链
  void CreateSwapChain();
  // 创建描述符堆
  void CreateRtvAndDsvDescriptorHeaps();

  //
  // 创建几何体
  //
  void BuildMesh_Shapes();      // 创建形状
  void BuildMesh_Land();        // 创建地形
  void BuildMesh_Waves();       // 创建波浪
  void BuildMesh_Box();         // 创建立方体
  void BuildMesh_Room();        // 创建房间
  void BuildMesh_Skull();       // 创建骷髅头
  void BuildMesh_TreeSprites(); // 树的公告牌

  //
  // 创建渲染对象
  //
  void BuildRenderItems_Shapes(); // 立方体（祭坛）

  // 创建用于CBV（常量缓冲区）的描述符堆（用于纹理）
  void BuildDescriptorHeaps_Room();

  // 创建常量缓冲区
  void BuildConstantBufferViews();
  // 创建根签名
  void BuildRootSignature();
  // 创建Shader
  void BuildShaderAndInputLayout();

  // 得到生成山地的法线
  XMFLOAT3 GetHillsNormal(float x, float z) const;
  float GetHillsHeight(float x, float z) const;

  // 创建帧缓冲区

  // 为SwapChain创建渲染目标视图缓冲区
  void CreateRenderTargetView();
  // 为SwapChain创建深度/模板缓冲区及其视图
  void CreateDepthStencilView();
  // 更新视口与剪裁区域
  void UpdateViewport();

private:
  ComPtr<IDXGIFactory4> factory_;
  ComPtr<ID3D12Device> device_;
  ComPtr<IDXGIAdapter> warp_adapter_;
  ComPtr<ID3D12Fence> fence_;
  ComPtr<ID3D12CommandQueue> command_queue_;
  ComPtr<ID3D12CommandAllocator> command_allocator_;
  ComPtr<ID3D12GraphicsCommandList> command_list_;
  ComPtr<IDXGISwapChain> swap_chain_;
  // Render Target View = 渲染目标视图资源
  ComPtr<ID3D12DescriptorHeap> rtv_heap_;
  // Depth/Stencil View = 深度/模板视图资源
  ComPtr<ID3D12DescriptorHeap> dsv_heap_;
  // Constant Buffer View = 常量缓冲区视图
  ComPtr<ID3D12DescriptorHeap> cbv_heap_;
  // 用于纹理的SRV（Shader Resource View = 着色器资源视图）
  ComPtr<ID3D12DescriptorHeap> srv_descriptor_heap_;
  ComPtr<ID3D12Resource> swap_chain_buffer_[SWAP_CHAIN_BUFFER_COUNT];
  ComPtr<ID3D12Resource> depth_stencil_buffer_;
  ComPtr<ID3D12RootSignature> root_signature_;
  ComPtr<ID3D12RootSignature> post_processing_signature_;
  ComPtr<ID3D12RootSignature> sobel_signature_;
  ComPtr<ID3D12RootSignature> waves_signature_;
  ComPtr<ID3D12PipelineState> pipeline_state_;

  UINT rtv_descriptor_size_;
  UINT dsv_descriptor_size_;
  UINT cbv_srv_uav_descriptor_size_;
  UINT64 current_fence_;

  D3D_DRIVER_TYPE driver_type_ = D3D_DRIVER_TYPE_HARDWARE;
  DXGI_FORMAT back_buffer_format_ = DXGI_FORMAT_R8G8B8A8_UNORM;
  int current_back_buffer_ = 0;
  DXGI_FORMAT depth_stencil_format_ = DXGI_FORMAT_D24_UNORM_S8_UINT;

  D3D12_VIEWPORT screen_viewport_;
  D3D12_RECT scissor_rect_;

  bool is_wire_frame_ = false; // 是否显示线框模式
  bool msaa_enable_ = false;   // 4X MSAA 是否启用
  UINT msaa_quality_ = 0;      // 4X MSAA 质量级别

  int client_width_;  // 窗口宽度
  int client_height_; // 窗口高度
  HWND hwnd_;         // 窗口句柄

  // 用于相机
  Camera camera_;
  SphericalCamera spherical_camera_;
  CameraType camera_type_ = CameraType::NORMAL;
  POINT last_mouse_pos_;

  std::unique_ptr<UploadBuffer<ObjectConstants>> obj_constants_;
  // ComPtr<ID3DBlob> vertex_shader_;
  // ComPtr<ID3DBlob> pixel_shader_;
  std::unordered_map<std::string, ComPtr<ID3DBlob>> shaders_;
  std::vector<D3D12_INPUT_ELEMENT_DESC> input_layout_;
  std::vector<D3D12_INPUT_ELEMENT_DESC> tree_sprite_input_layout_;
  std::vector<D3D12_INPUT_ELEMENT_DESC> tess_input_layout_;
  std::unique_ptr<SimpleMesh> box_;
  std::unique_ptr<SimpleMesh> geo_;
  std::unordered_map<std::string, std::unique_ptr<SimpleMesh>> geometries_;
  std::unordered_map<std::string, ComPtr<ID3D12PipelineState>> pipelines_;

  // 用于帧资源
  std::vector<std::unique_ptr<FrameResource>> frame_resources_;
  FrameResource* current_frame_resource_;
  int frame_resource_index_;
  // 游戏主PASS信息（全局）
  PassConstants main_pass_;
  // 用于反射项目，将光源进行镜像
  PassConstants reflected_pass_;
  // PASS在CBV中的位置
  UINT pass_cbv_offset_;

  // 游戏对象（GameObject）的总队列
  std::vector<std::unique_ptr<RenderItem>> items_;
  // 根据PSO来划分渲染项目
  std::vector<RenderItem*> opaque_items_;
  std::vector<RenderItem*> transparent_items_;
  std::vector<RenderItem*> render_layer[(int)RenderLayer::Count];

  DxScene* scene_;

  // 材质
  std::unordered_map<std::string, std::unique_ptr<Material>> materials_;
  // 纹理
  std::unordered_map<std::string, std::unique_ptr<Texture>> textures_;

  // 用于太阳光
  float sum_theta_ = 1.25f * XM_PI;
  float sum_phi_ = XM_PIDIV4;

  // 用于阴影/镜面的渲染
  RenderItem* skull_item_ = nullptr;
  RenderItem* reflected_skull_item_ = nullptr;
  RenderItem* reflected_floor_item_ = nullptr;
  RenderItem* shadowed_skull_item_ = nullptr;
  XMFLOAT3 skull_translation = {0.0f, 1.0f, -5.0f};

  // 用于相机
  XMFLOAT3 eye_pos_ = {0.0f, 0.0f, 0.0f};
  XMFLOAT4X4 view_ = IDENTITY_4X4;
  XMFLOAT4X4 projection_ = IDENTITY_4X4;

  // 用于累加的计算
  ComPtr<ID3D12Resource> mInputBufferA = nullptr;
  ComPtr<ID3D12Resource> mInputUploadBufferA = nullptr;
  ComPtr<ID3D12Resource> mInputBufferB = nullptr;
  ComPtr<ID3D12Resource> mInputUploadBufferB = nullptr;
  ComPtr<ID3D12Resource> mOutputBuffer = nullptr;
  ComPtr<ID3D12Resource> mReadBackBuffer = nullptr;

  // 用于模糊
  std::unique_ptr<BlurFilter> blur_filter_;
  bool is_blur_enable_ = false; // 模糊的开关

  // 用于波浪
  std::unique_ptr<Waves> waves_;
  RenderItem* waves_item_ = nullptr;
  std::unique_ptr<GpuWaves> gpu_waves_ = nullptr;

  // 用于索贝尔算子
  std::unique_ptr<SobelFilter> sobel_filter_ = nullptr;
  std::unique_ptr<RenderTarget> offscreen_rt_ = nullptr;
  D3D12_VERTEX_BUFFER_VIEW empty_vertex_buffer_;
  D3D12_INDEX_BUFFER_VIEW empty_index_buffer_;
  ComPtr<ID3D12Resource> emptyIndexBuffer;

  // 用于剔除
  BoundingFrustum camera_frustum_;
  bool mFrustumCullingEnabled = true;
  std::string mMainWndCaption = std::string("DxEngine");

  // 用于拾取
  RenderItem* mPickedRitem = nullptr;

  // 用于天空盒
  UINT mSkyTexHeapIndex = 0;
  RenderItem* mSkullRitem = nullptr;
  Camera mCubeMapCamera[6];
  std::unique_ptr<CubeRenderTarget> mDynamicCubeMap = nullptr;
  CD3DX12_CPU_DESCRIPTOR_HANDLE mCubeDSV;
  UINT mDynamicTexHeapIndex = 0;
  ComPtr<ID3D12Resource> mCubeDepthStencilBuffer;

  // 用于阴影
  PassConstants mShadowPassCB; // index 1 of pass cbuffer.
  std::unique_ptr<ShadowMap> mShadowMap;
  float mLightRotationAngle = 0.0f;
  XMFLOAT3 mBaseLightDirections[3] = {XMFLOAT3(0.57735f, -0.57735f, 0.57735f),
      XMFLOAT3(-0.57735f, -0.57735f, 0.57735f),
      XMFLOAT3(0.0f, -0.707f, -0.707f)};
  XMFLOAT3 mRotatedLightDirections[3];
  UINT mShadowMapHeapIndex = 0;
  UINT mNullCubeSrvIndex = 0;
  UINT mNullTexSrvIndex = 0;
  CD3DX12_GPU_DESCRIPTOR_HANDLE mNullSrv;
  XMFLOAT4X4 mShadowTransform = IDENTITY_4X4;
  float mLightNearZ = 0.0f;
  float mLightFarZ = 0.0f;
  XMFLOAT3 mLightPosW;
  XMFLOAT4X4 mLightView = IDENTITY_4X4;
  XMFLOAT4X4 mLightProj = IDENTITY_4X4;
  DirectX::BoundingSphere mSceneBounds;

  // 用于环境光遮蔽
  std::unique_ptr<Ssao> mSsao;
  ComPtr<ID3D12RootSignature> mSsaoRootSignature = nullptr;
  UINT mSsaoHeapIndexStart = 0;
  UINT mSsaoAmbientMapIndex = 0;
  UINT mNullTexSrvIndex1 = 0;
  UINT mNullTexSrvIndex2 = 0;

  // 用于蒙皮骨骼
  UINT mSkinnedSrvHeapStart = 0;
  std::string mSkinnedModelFilename = "Models\\soldier.m3d";
  std::unique_ptr<SkinnedModelInstance> mSkinnedModelInst;
  SkinnedData mSkinnedInfo;
  std::vector<M3DLoader::Subset> mSkinnedSubsets;
  std::vector<M3DLoader::M3dMaterial> mSkinnedMats;
  std::vector<std::string> mSkinnedTextureNames;
  std::vector<D3D12_INPUT_ELEMENT_DESC> mSkinnedInputLayout;
};

// 用于和教程中的示例进行替换。每次示例都自已替换太浪费时间了。
#define md3dDevice device_
#define mMainPassCB main_pass_
#define mCommandList command_list_
#define mRtvHeap rtv_heap_
#define mRtvDescriptorSize rtv_descriptor_size_
#define mTextures textures_
#define mCbvSrvDescriptorSize cbv_srv_uav_descriptor_size_
#define mShaders shaders_
#define mInputLayout input_layout_
#define mGeometries geometries_
#define mMaterials materials_
#define mAllRitems items_
#define mOpaqueRitems opaque_items_
#define mRootSignature root_signature_
#define mBackBufferFormat back_buffer_format_
#define mDepthStencilFormat depth_stencil_format_
#define m4xMsaaState msaa_enable_
#define m4xMsaaQuality msaa_quality_
#define mPSOs pipelines_
#define mScreenViewport screen_viewport_
#define mScissorRect scissor_rect_
#define mSrvDescriptorHeap srv_descriptor_heap_
#define mCommandQueue command_queue_
#define mSwapChain swap_chain_
#define mCurrBackBuffer current_back_buffer_
#define SwapChainBufferCount SWAP_CHAIN_BUFFER_COUNT
#define mCurrentFence current_fence_
#define mFence fence_
#define mCamera camera_
#define mCamFrustum camera_frustum_
#define mCurrFrameResource current_frame_resource_
#define mRitemLayer render_layer
#define mClientWidth client_width_
#define mClientHeight client_height_
#define gNumFrameResources FRAME_RESOURCE_COUNT
#define mCbvSrvUavDescriptorSize cbv_srv_uav_descriptor_size_
#define mDsvDescriptorSize dsv_descriptor_size_
#define mDsvHeap dsv_heap_
#define mDepthStencilBuffer depth_stencil_buffer_

} // namespace ifire
